package com.chatroom.client;

// 导入我们新创建的类
import com.chatroom.client.model.ChatMessage;
import com.chatroom.client.model.MessageType;
import com.chatroom.client.ui.MessageListCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class Client {

    // --- 网络核心组件 ---
    private Socket socket;
    private PrintWriter pw;
    private String nickname;

    // --- UI 核心组件 ---
    private JFrame frame;
    private JList<ChatMessage> messageList;
    private DefaultListModel<ChatMessage> listModel;
    private JTextArea inputArea;
    private JButton sendButton;
    private JPopupMenu emojiPicker;

    // --- 资源缓存 ---
    private final Map<String, ImageIcon> avatarCache = new HashMap<>();
    private final Map<String, Map<String, ImageIcon>> allEmojis = new HashMap<>();
    private final Map<String, String> categoryIcons = new HashMap<>();
    // [NEW] 这是我们专为渲染器准备的扁平化数据
    private final Map<String, ImageIcon> flatEmojiCache = new HashMap<>();
    private static final int AVATAR_SIZE = 40;

    public Client(String nickname) {
        this.nickname = nickname;
        loadEmojis(); // 1. 加载资源

        // 2. 连接服务器
        try {
            socket = new Socket("localhost", 8088);
            pw = new PrintWriter(
                    new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8)), true);
        } catch (IOException e) {
            showErrorDialog("无法连接到服务器，请确保服务器已启动。");
            System.exit(1);
        }

        // 3. 在EDT中创建并显示GUI
        SwingUtilities.invokeLater(() -> {
            createAndShowGUI();
            // promptForNickname(); // 不再弹窗输入昵称
            pw.println(nickname); // 直接发送昵称
            frame.setTitle("聊天室 - " + nickname);
            startServerHandler();
        });
    }

    private void createAndShowGUI() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        frame = new JFrame("聊天室");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 800);
        frame.setLocationRelativeTo(null);

        JPanel contentPane = new JPanel(new BorderLayout());
        contentPane.setBackground(new Color(245, 245, 245));
        frame.setContentPane(contentPane);

        listModel = new DefaultListModel<>();
        messageList = new JList<>(listModel);
        // !! 关键改动：使用新的、独立的渲染器类，并传入所需的资源 !!
        messageList.setCellRenderer(new MessageListCellRenderer(avatarCache, flatEmojiCache, AVATAR_SIZE));
        messageList.setBackground(new Color(245, 245, 245));
        // [NEW] 添加这两行来移除选中时的蓝色背景
        messageList.setSelectionBackground(new Color(0, 0, 0, 0)); // 设置选择背景为完全透明
        messageList.setSelectionForeground(Color.BLACK); // 确保文字颜色不变（虽然我们的气泡有自己的颜色，但这不影响）
        JScrollPane messageScrollPane = new JScrollPane(messageList);
        messageScrollPane.setBorder(null);

        JPanel bottomPanel = createBottomPanel();

        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, messageScrollPane, bottomPanel);
        splitPane.setResizeWeight(1.0);
        splitPane.setBorder(null);

        contentPane.add(splitPane, BorderLayout.CENTER);
        SwingUtilities.invokeLater(() -> splitPane.setDividerLocation(0.8));
        frame.setVisible(true);
    }

    private JPanel createBottomPanel() {
        JPanel bottomPanel = new JPanel(new BorderLayout(0, 5));
        bottomPanel.setBackground(new Color(245, 245, 245));
        bottomPanel.setBorder(new EmptyBorder(0, 10, 5, 10));

        JToolBar toolBar = createToolBar();
        bottomPanel.add(toolBar, BorderLayout.NORTH);

        JPanel mainInputPanel = new JPanel(new BorderLayout());
        mainInputPanel.setOpaque(false);

        inputArea = new JTextArea();
        inputArea.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        inputArea.setLineWrap(true);
        inputArea.setWrapStyleWord(true);
        inputArea.setRows(4);
        inputArea.setBorder(new EmptyBorder(8, 8, 8, 8));
        setupInputAreaKeyBindings();
        JScrollPane inputScrollPane = new JScrollPane(inputArea);
        inputScrollPane.setBorder(BorderFactory.createLineBorder(new Color(220, 220, 220)));
        mainInputPanel.add(inputScrollPane, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        buttonPanel.setOpaque(false);
        buttonPanel.setBorder(new EmptyBorder(5, 0, 0, 0));
        sendButton = new JButton("发送(Enter)");
        sendButton.setBackground(new Color(30, 111, 255));
        sendButton.setForeground(Color.WHITE);
        sendButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
        sendButton.setPreferredSize(new Dimension(130, 32));
        sendButton.setOpaque(true);
        sendButton.setBorderPainted(false);
        sendButton.setFocusPainted(false);
        sendButton.setMnemonic(KeyEvent.VK_S);
        sendButton.addActionListener(e -> sendMessage());
        buttonPanel.add(sendButton);
        mainInputPanel.add(buttonPanel, BorderLayout.SOUTH);

        bottomPanel.add(mainInputPanel, BorderLayout.CENTER);
        return bottomPanel;
    }

    private void setupInputAreaKeyBindings() {
        InputMap inputMap = inputArea.getInputMap(JComponent.WHEN_FOCUSED);
        ActionMap actionMap = inputArea.getActionMap();
        KeyStroke enterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        inputMap.put(enterStroke, "sendMessage");
        actionMap.put("sendMessage", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sendMessage();
            }
        });
        KeyStroke shiftEnterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK);
        inputMap.put(shiftEnterStroke, "insertBreak");
    }

    private JToolBar createToolBar() {
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.setRollover(true);
        toolBar.setBorder(new EmptyBorder(5, 0, 5, 0));
        toolBar.setBackground(new Color(245, 245, 245));

        JButton emojiButton = createToolBarButton("☺", "表情");

        emojiButton.addActionListener(e -> {
            if (emojiPicker == null) {
                createEmojiPicker();
            }
            // 新代码: 计算正确的Y坐标，使其在按钮上方弹出
            int yPosition = -emojiPicker.getPreferredSize().height;
            emojiPicker.show(emojiButton, 0, yPosition);
        });
        toolBar.add(emojiButton);
        // 截图按钮
        JButton screenshotButton = createToolBarButton("✂", "截图 (开发中)");
        screenshotButton.addActionListener(e -> showPlaceholderDialog("截图功能"));
        toolBar.add(screenshotButton);
        // 发送图片按钮
        JButton imageButton = createToolBarButton("🖼", "发送图片 (开发中)");
        imageButton.addActionListener(e -> showPlaceholderDialog("发送图片功能"));
        toolBar.add(imageButton);
        // 发送文件按钮
        JButton fileButton = createToolBarButton("📁", "发送文件 (开发中)");
        fileButton.addActionListener(e -> showPlaceholderDialog("发送文件功能"));
        toolBar.add(fileButton);

        // 语音通话按钮
        JButton callButton = createToolBarButton("📞", "语音通话 (开发中)");
        callButton.addActionListener(e -> showPlaceholderDialog("语音通话功能"));
        toolBar.add(callButton);
        // --- 3. [NEW] 添加弹簧，将后续组件推向右侧 ---
        toolBar.add(Box.createHorizontalGlue());
        // --- 4. [NEW] 添加右侧的按钮 ---

        // 聊天记录按钮
        JButton historyButton = createToolBarButton("💬", "聊天记录 (开发中)");
        historyButton.addActionListener(e -> showPlaceholderDialog("聊天记录功能"));
        toolBar.add(historyButton);
        // ... 其他按钮 ...
        return toolBar;
    }

    // [NEW] 添加一个新的辅助方法，用于显示功能占位提示
    private void showPlaceholderDialog(String featureName) {
        JOptionPane.showMessageDialog(frame,
                featureName + " 正在努力开发中，敬请期待！",
                "功能提示",
                JOptionPane.INFORMATION_MESSAGE);
    }

    private JButton createToolBarButton(String text, String tooltip) {
        JButton button = new JButton(text);
        button.setToolTipText(tooltip);
        button.setFont(new Font("Segoe UI Symbol", Font.PLAIN, 18));
        button.setFocusPainted(false);
        button.setBorderPainted(false);
        button.setContentAreaFilled(false);
        button.setMargin(new Insets(2, 5, 2, 5));
        return button;
    }

    // [MODIFIED] 完全重写 createEmojiPicker 来构建高级UI
    private void createEmojiPicker() {
        emojiPicker = new JPopupMenu();
        emojiPicker.setBorder(BorderFactory.createLineBorder(new Color(220, 220, 220)));
        emojiPicker.setLayout(new BorderLayout()); // PopupMenu自身也使用布局
        // --- 1. 创建主面板 ---
        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.setPreferredSize(new Dimension(400, 300)); // 给选择器一个合适的初始大小
        // --- 2. 创建顶部标题栏 (NORTH) ---
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBorder(new EmptyBorder(8, 12, 8, 12));
        headerPanel.setBackground(Color.WHITE);
        final JLabel categoryTitle = new JLabel("经典表情"); // 初始标题
        categoryTitle.setFont(new Font("微软雅黑", Font.BOLD, 14));
        JButton settingsButton = createToolBarButton("⚙", "表情设置 (开发中)");
        settingsButton.addActionListener(e -> showPlaceholderDialog("表情管理"));
        headerPanel.add(categoryTitle, BorderLayout.WEST);
        headerPanel.add(settingsButton, BorderLayout.EAST);
        mainPanel.add(headerPanel, BorderLayout.NORTH);
        // --- 3. 创建中部表情展示区 (CENTER), 使用CardLayout ---
        final JPanel emojiPagesPanel = new JPanel(new CardLayout());
        emojiPagesPanel.setOpaque(false);
        // --- 4. 创建底部自分类切换栏 (SOUTH) ---
        JToolBar categoryToolBar = new JToolBar();
        categoryToolBar.setFloatable(false);
        categoryToolBar.setBorder(new EmptyBorder(4, 8, 4, 8));
        categoryToolBar.setBackground(new Color(248, 248, 248));
        ButtonGroup categoryGroup = new ButtonGroup(); // 确保一次只有一个分类被选中
        // --- 5. 动态创建每个分类的页面和切换按钮 ---
        for (Map.Entry<String, String> categoryEntry : categoryIcons.entrySet()) {
            String categoryName = categoryEntry.getKey();
            String categoryIcon = categoryEntry.getValue();
            // A. 创建该分类的表情网格页面
            JPanel gridPanel = new JPanel(new GridLayout(0, 8, 4, 4)); // 8列，间距4x4
            gridPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
            gridPanel.setBackground(Color.WHITE);

            Map<String, ImageIcon> emojis = allEmojis.get(categoryName);
            if (emojis != null) {
                for (Map.Entry<String, ImageIcon> entry : emojis.entrySet()) {
                    JButton emojiButton = new JButton(
                            new ImageIcon(entry.getValue().getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH)));
                    emojiButton.setToolTipText(entry.getKey());
                    emojiButton.setBorder(BorderFactory.createEmptyBorder());
                    emojiButton.setContentAreaFilled(false);
                    emojiButton.setFocusPainted(false);
                    emojiButton.addActionListener(e -> {
                        inputArea.insert(entry.getKey(), inputArea.getCaretPosition());
                        emojiPicker.setVisible(false);
                        inputArea.requestFocusInWindow();
                    });
                    gridPanel.add(emojiButton);
                }
            }
            JScrollPane scrollPane = new JScrollPane(gridPanel);
            scrollPane.setBorder(null);
            // 添加到CardLayout面板中
            emojiPagesPanel.add(scrollPane, categoryName);
            // B. 创建对应的切换按钮
            JToggleButton categoryButton = new JToggleButton(categoryIcon);
            categoryButton.setToolTipText(categoryName);
            setupCategoryButton(categoryButton); // 提取一个方法来设置样式
            categoryButton.addActionListener(e -> {
                CardLayout cl = (CardLayout) (emojiPagesPanel.getLayout());
                cl.show(emojiPagesPanel, categoryName);
                categoryTitle.setText(categoryName + "表情"); // 更新标题
            });
            categoryGroup.add(categoryButton);
            categoryToolBar.add(categoryButton);
        }

        // 默认选中第一个分类
        ((JToggleButton) categoryToolBar.getComponent(0)).setSelected(true);
        mainPanel.add(emojiPagesPanel, BorderLayout.CENTER);
        mainPanel.add(categoryToolBar, BorderLayout.SOUTH);
        // --- 6. 将主面板添加到JPopupMenu ---
        emojiPicker.add(mainPanel);
    }

    // [NEW] 辅助方法，用于统一设置分类按钮的样式
    private void setupCategoryButton(JToggleButton button) {
        button.setFont(new Font("Segoe UI Symbol", Font.PLAIN, 18));
        button.setFocusPainted(false);
        button.setBorder(new EmptyBorder(4, 8, 4, 8));
        button.setContentAreaFilled(false);
        // 当按钮被选中时，给它一个不同的背景
        button.addChangeListener(e -> {
            if (button.isSelected()) {
                button.setOpaque(true);
                button.setBackground(new Color(220, 220, 220));
            } else {
                button.setOpaque(false);
                button.setBackground(null);
            }
        });
    }

    private void sendMessage() {
        String content = inputArea.getText();
        if (content.trim().isEmpty()) {
            return;
        }
        // 使用我们独立的ChatMessage和MessageType类
        ChatMessage message = new ChatMessage(nickname, content, true, LocalDateTime.now(), MessageType.USER);
        addMessage(message);
        pw.println(content);
        inputArea.setText("");
        inputArea.requestFocusInWindow();
    }

    private void addMessage(ChatMessage message) {
        SwingUtilities.invokeLater(() -> {
            listModel.addElement(message);
            int lastIndex = listModel.getSize() - 1;
            if (lastIndex >= 0) {
                messageList.ensureIndexIsVisible(lastIndex);
            }
        });
    }

    private void promptForNickname() {
        nickname = JOptionPane.showInputDialog(frame, "请输入您的昵称:", "设置昵称", JOptionPane.PLAIN_MESSAGE);
        if (nickname == null || nickname.trim().isEmpty()) {
            System.exit(0);
        }
        pw.println(nickname);
        frame.setTitle("聊天室 - " + nickname);
    }

    private void startServerHandler() {
        new Thread(() -> {
            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))) {
                String rawMessage;
                while ((rawMessage = br.readLine()) != null) {
                    ChatMessage message;
                    if (rawMessage.startsWith("SYS:")) {
                        message = new ChatMessage("System", rawMessage.substring(4), false, LocalDateTime.now(),
                                MessageType.SYSTEM);
                    } else {
                        String[] parts = rawMessage.split(": ", 2);
                        if (parts.length == 2) {
                            message = new ChatMessage(parts[0], parts[1], false, LocalDateTime.now(), MessageType.USER);
                        } else {
                            message = new ChatMessage("System", rawMessage, false, LocalDateTime.now(),
                                    MessageType.SYSTEM);
                        }
                    }
                    addMessage(message);
                }
            } catch (IOException e) {
                showErrorDialog("与服务器的连接已断开。");
            } finally {
                sendButton.setEnabled(false);
                inputArea.setEnabled(false);
            }
        }).start();
    }

    private void showErrorDialog(String message) {
        JOptionPane.showMessageDialog(frame, message, "错误", JOptionPane.ERROR_MESSAGE);
    }

    // 文件: src/com/chatroom/client/Client.java

    // [MODIFIED] 重写 loadEmojis 以支持分类
    private void loadEmojis() {
        // 定义分类及其图标 (使用Unicode字符)
        categoryIcons.put("经典", "☺");
        categoryIcons.put("心情", "❤");
        categoryIcons.put("动物", "🐾");

        // -- 加载"经典"分类的表情 --
        Map<String, ImageIcon> classicEmojis = new LinkedHashMap<>(); // 使用LinkedHashMap保持顺序
        String[] classicNames = { "smile", "cry", "angry", "cool", "blush", "doge", "heart", "sob", "tongue", "wink" };
        for (String name : classicNames) {
            String code = "[" + name + "]";
            String path = "/emojis/" + name + ".png"; // 确保这些图片在你的 resources/emojis 目录下
            URL url = getClass().getResource(path);
            if (url != null) {
                classicEmojis.put(code, new ImageIcon(url));
            } else {
                System.err.println("无法加载表情: " + path);
            }
        }
        allEmojis.put("经典", classicEmojis);

        // -- 加载"心情"分类的表情 (示例，你需要准备对应的图片) --
        Map<String, ImageIcon> moodEmojis = new LinkedHashMap<>();
        String[] moodNames = { "love", "sad", "wow", "laugh", "sleepy" };
        for (String name : moodNames) {
            String code = "[" + name + "]";
            String path = "/emojis/" + name + ".png";
            URL url = getClass().getResource(path);
            if (url != null) {
                moodEmojis.put(code, new ImageIcon(url));
            }
        }
        allEmojis.put("心情", moodEmojis);

        // -- 加载"动物"分类的表情 (示例) --
        Map<String, ImageIcon> animalEmojis = new LinkedHashMap<>();
        String[] animalNames = { "cat", "pig", "penguin" };
        for (String name : animalNames) {
            String code = "[" + name + "]";
            String path = "/emojis/" + name + ".png";
            URL url = getClass().getResource(path);
            if (url != null) {
                animalEmojis.put(code, new ImageIcon(url));
            }
        }
        allEmojis.put("动物", animalEmojis);
        // 遍历所有分类
        for (Map<String, ImageIcon> categoryMap : allEmojis.values()) {
            // 将该分类下的所有表情（一个Map）全部添加到扁平缓存中
            flatEmojiCache.putAll(categoryMap);
        }

        System.out.println("表情加载完成。共加载 " + flatEmojiCache.size() + " 个表情。"); // 添加一行日志，方便调试
        // 你可以继续添加更多分类...
    }

    public static void main(String[] args) {
        System.setProperty("file.encoding", "UTF-8");
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            UIManager.put("Label.font", new Font("微软雅黑", Font.PLAIN, 14));
            UIManager.put("Button.font", new Font("微软雅黑", Font.PLAIN, 14));
            UIManager.put("TextField.font", new Font("微软雅黑", Font.PLAIN, 14));
            UIManager.put("TextArea.font", new Font("微软雅黑", Font.PLAIN, 14));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 登录后应传入昵称
        // new Client(); // 原有方式
    }
}
